# encoding:utf-8
# python script to publish jenkins's build to Zentao
import requests
import warnings
import json
import os
import time
try:
    import jenkins 
except:
    print("python-jenkins is required")
    print("try install it with following command: ")
    print("pip install python-jenkins")
    exit(-7)

from getpass import getpass
import json
# import mimetypes
try:
    from requests_toolbelt import MultipartEncoder
except:
    print("missing requests_toolbelt package")
    print("try install it with following command:")
    print("pip install requests_toolbelt")
    exit(-9)

LAST_CREATED_BUILD_URL=""

class ZenTao:
    """
    控制禅道的类
    """
    host = str
    session_name = str
    session_id = str
    session = requests.Session
    boundary = str
    multipart_header = {}

    def __init__(self, host: str):
        self.host = host
        self.session = requests.Session()
        self.boundary = '------WebKitFormBoundaryAmOiBfmEYFBzUOnO'
        self.multipart_header = {'Content-Type': 'multipart/form-data; boundary={0}'.format(self.boundary),
                                 'charset': 'UTF-8'}

    def login(self, username: str, password: str):
        """
        登录禅道
        :return: 是否成功
        """
        respond = self.session.get(self.host + '/zentao/api-getsessionid.json')
        # print(req_get_session.content)
        if respond.status_code != 200:
            warnings.warn('http error: %d' % respond.status_code)
            return False
        content = respond.json()
        # print(content)
        if content['status'] != 'success':
            warnings.warn('获取链接session失败')
            return False
        # md5_value = hashlib.md5(content['data'])
        # if md5_value != content['md5']:
        #     warnings.warn("数据md5校验错误")
        #     return False
        data = json.loads(content['data'])
        self.session_name = data['sessionName']
        self.session_id = data['sessionID']
        # print(self.session_name + '=' + self.session_id)
        params = {'account': username, 'password': password}
        # headers = {'Content-Type': 'application/x-www-form-urlencoded'}
        respond = self.session.post(self.host + '/zentao/user-login.json?{0}={1}'
                                    .format(self.session_name, self.session_id),
                                    params=params)
        if respond.status_code != 200:
            warnings.warn('http error: %d' % respond.status_code)
            return False
        # print(respond.content)
        content = respond.json()
        if content['status'] != 'success':
            warnings.warn('登录失败')
            return False
        return True

    def logout(self):
        '''
        退出禅道
        :return: 是否成功
        '''
        respond = self.session.get(self.host + '/zentao/user-logout.json')
        if respond.status_code != 200:
            warnings.warn('http error: %d' % respond.status_code)
            return False
        # print(respond.content)
        content = respond.json()
        if content['status'] != 'success':
            warnings.warn('登录失败')
            return False
        return True

    def get_index(self):
        """
        获取首页
        :return:
        """
        respond = self.session.get(self.host + '/zentao/branch-sort.json?{0}={1}'
                                   .format(self.session_name, self.session_id))
        if respond.status_code != 200:
            warnings.warn('http error: %d' % respond.status_code)
            return False
        print(respond.content)
        return True

    def get_build(self, id: int):
        """
        获取版本
        :return:
        """
        data = {'buildID': id}
        req = self.session.get(
            self.host + '/zentao/build-view-{0}.json?{1}={2}'.format(
                str(id), self.session_name, self.session_id),
            params=data)
        if req.status_code != 200:
            warnings.warn('http error: %d' % req.status_code)
            return False
        # content = req.json()
        # print(req.headers)
        # data = json.loads(content['data'], 'utf-8')
        # print(data['title'])
        return True

    def create_build(self, product: int, project: int, name: str, builder: str, source: str, download: str,
                     files: list, desc: str):
        """
        获取版本
        :return:
        """
        data = {'projectID': project}
        respond = self.session.get(
            self.host + '/zentao/build-create-{0}.json?{1}={2}'
            .format(str(project), self.session_name, self.session_id),
            params=data)
        if respond.status_code != 200:
            warnings.warn('http error: %d' % respond.status_code)
            return ""
        fields = {
            'product': str(product),
            'name': name,
            'builder': builder,
            'date': time.strftime('%Y-%m-%d', time.localtime(time.time())),
            'scmPath': source,
            'filePath': download,
            'desc': desc
        }
        file_index = 0
        for file_name in files:
            file_bin: bytes
            mime_type: str
            try:
                fd = open(file_name, 'rb')
                # mime_type = mimetypes.guess_type(file)[0]
                # if mime_type is None:
                mime_type = 'application/octet-stream'
                file_bin = fd.read()
                fd.close()
            except IOError as err:
                warnings.warn('failed to open file: ' + file_name + ' with' + err.__str__())
                continue
            fields["files[" + str(file_index) + "]"] = (
                os.path.basename(file_name), file_bin, mime_type)
            file_index += 1

        data = MultipartEncoder(
            fields=fields
        )

        # print(data)

        respond = self.session.post(
            self.host + '/zentao/build-create-{0}.json?{1}={2}'
            .format(str(project), self.session_name, self.session_id),
            headers={'Content-Type': data.content_type, 'charset': 'UTF-8'}, data=data)
        if respond.status_code != 200:
            warnings.warn('http error: %d' % respond.status_code)
            return ""
        content = respond.json()
        if content['result'] != 'success':
            warnings.warn('创建失败')
            return "" 
        resp_json = json.loads(respond.content)
        print(resp_json)
        return self.host + resp_json['locate']

    def delete_build(self, id: int):
        """
        删除版本
        :return:
        """
        data = {'buildID': id, 'confirm': 'yes'}
        respond = requests.get(
            self.host + '/zentao/build-delete-{0}-yes.json?{1}={2}'.format(
                str(id), self.session_name, self.session_id),
            params=data)
        if respond.status_code != 200:
            warnings.warn('http error: %d' % respond.status_code)
            return False
        # content = req.json()
        print(respond.content)
        # data = json.loads(content['data'], 'utf-8')
        # print(data['title'])
        return True


# example code
# if __name__ == '__main__':
#     z = ZenTao('http://git.roombanker.cn:801')
#     if z.login('ysy', 'ddd'):
#         print('登录成功')
#     if z.create_build(0, 354, 'test', 'admin', 'github.com', 'ftp://192.168.1.1',
#                       ['../a.zip', '../b.zip'], 'describe'):
#         print("创建版本")
#     if z.logout():
#         print('注销成功')
#
DEV_TEST = False
# DEV_TEST = True 
ZENTAO_URL="http://git.roombanker.cn:801"
ZENTAO_USER=""
ZENTAO_PASS=""
CI_URL="https://ci.tvlinker.com:8443"
CI_USER=""
CI_PASS=""

BUILD_NUMBER = 0 
def input_zentao_user_pass():
    if DEV_TEST:
        return
    global ZENTAO_USER
    global ZENTAO_PASS
    ZENTAO_USER = input("请输入禅道用户名:")
    ZENTAO_PASS = getpass("请输入禅道密码:")

def input_jenkins_user_pass():
    if DEV_TEST:
        return
    global CI_USER
    global CI_PASS
    CI_USER = input("请输入Jekins用户名:")
    CI_PASS = getpass("请输入Jekins密码:")

def input_jenkins_build_number():
    if DEV_TEST:
        return
    
    global BUILD_NUMBER
    url = input("请输入Jenkins URL:")
    url = url.replace(CI_URL, "").replace("job", "").replace("RBF_BUILD", "").replace("/", "")
    BUILD_NUMBER = url.strip()

def main():
    input_zentao_user_pass()
    z = ZenTao(ZENTAO_URL)
    if z.login(ZENTAO_USER, ZENTAO_PASS):
        print("禅道登录成功")
    else:
        print("禅道登录失败")
        exit(-1)

    f = open("prj_lst.json", "r")
    prj_lst = json.load(f)
    input_jenkins_user_pass()
    ci = jenkins.Jenkins(CI_URL, CI_USER, CI_PASS)

    try:
        _ = ci.get_whoami()
    except:
        print("Jenkins 登录失败")
        exit(-8)

    input_jenkins_build_number()
    build = ci.get_build_info('RBF_BUILD', BUILD_NUMBER)

    print("BUILD_NUMBER: {0}, 显示名称: {1} \n   描述:\n {2}\n\n".format(BUILD_NUMBER, build['displayName'], build['description']))

    yes_or_no = input("请确定要发布的构建是否正确? (N/y)")
    if yes_or_no.upper() != 'Y':
        print("用户选择退出")
        exit(-2)

    if build['building'] == True:
        print("Error: 该构建正在编译,请完成后再发布")
    
    prj_missing = False
    prj_names = []
    for file in build['artifacts']:
        filename = file['fileName']
        if not filename.endswith('.hex') or filename.find("_E0_") > 0:
            continue
        prj_name = filename[0:filename.find('_')]
        if prj_name not in prj_lst:
            print("错误!! 项目:  {0} 没有配置信息,请修改prj_lst.json".format(prj_name))
            prj_missing =  True
        prj_names.append(prj_name)

    if prj_missing:
        print("prj_list.json 未配置完整, 退出")
        exit(-3)
    
    description = build['description']
    url = "{0}/job/RBF_BUILD/{1}/".format(CI_URL, BUILD_NUMBER)
    download_url = "用户名： dqa_rbf  密码： bF8gzOWY#zFfyQG0"
    builds_pubed = {}
    for file in build['artifacts']:
        filename = file['fileName']
        
        if not filename.endswith('.hex') or filename.find("_E0_") > 0:
            continue
        prj_name = filename[0:filename.find('_')]
        project_id = prj_lst[prj_name]['project_id']
        product_id = prj_lst[prj_name]['product_id']
        build_name = filename[0:-4]
        build_url = z.create_build(product_id, project_id, build_name,  CI_USER, url, download_url, [], description)
        if build_url != "":
            build_url = build_url.replace(".json", ".html")
            print("{0}: {1}".format(build_name, build_url))
            builds_pubed[prj_name] = build_url
        else:
            print("{0}: 创建失败".format(build_name))
            exit(-4)

    print("#"*80)
    for prj_name in builds_pubed.keys():
        print("PRJ_NAME: {0} / URL:{1}".format(prj_name, builds_pubed[prj_name]))
    print("全部项目发布完成")

if __name__ == "__main__":
    main()
